Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 46 additions & 3 deletions en/appendices/5-0-migration-guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ ORM
- ``allowMultipleNulls`` option for ``isUnique`` rule now default to true matching
the original 3.x behavior.
- ``Table::query()`` has been removed in favor of query-type specific functions.
- ``Table::updateQuery()``, ``Table::selectQuery()``, ``Table::insertQuery()``, and `
`Table::deleteQuery()``) were added and return the new type-specific query objects below.
- ``Table::updateQuery()``, ``Table::selectQuery()``, ``Table::insertQuery()``, and
``Table::deleteQuery()``) were added and return the new type-specific query objects below.
- ``SelectQuery``, ``InsertQuery``, ``UpdateQuery`` and ``DeleteQuery`` were added
which represent only a single type of query and do not allow switching between query types nor
calling functions unrelated to the specific query type.
Expand Down Expand Up @@ -227,6 +227,14 @@ Database
``Connection`` methods are no longer proxied. This aligns the function name
with the SQL statement.

ORM
---

- Calling ``Table::find()`` with options array is deprecated. Use `named arguments <https://www.php.net/manual/en/functions.arguments.php#functions.named-arguments>`__
instead. For e.g. instead of ``find('all', ['conditions' => $array])`` use
``find('all', conditions: $array)``. Similarly for custom finder options, instead
of ``find('list', ['valueField' => 'name'])`` use ``find('list', valueField: 'name')``
or multiple named arguments like ``find(type: 'list', valueField: 'name', conditions: $array)``.

New Features
============
Expand Down Expand Up @@ -256,6 +264,42 @@ Database
- Supported drivers now automatically add auto-increment only to integer primary keys named "id" instead
of all integer primary keys. Setting 'autoIncrement' to false always disables on all supported drivers.

ORM
---

Table finders can now have typed arguments as required instead of an options array.
For e.g. a finder for fetching posts by category or user::

public function findByCategoryOrUser(SelectQuery $query, array $options)
{
if (isset($options['categoryId'])) {
$query->where('category_id' => $options['categoryId']);
}
if (isset($options['userId'])) {
$query->where('user_id' => $options['userId']);
}

return $query;
}

should now be written as::

public function findByCategoryOrUser(SelectQuery $query, ?int $categoryId = null, ?int $userId = null)
{
if ($categoryId) {
$query->where('category_id' => $categoryId);
}
if ($userId) {
$query->where('user_id' => $userId);
}

return $query;
}

The finder can then be called as ``find('byCategoryOrUser', userId: $somevar)``.
You can even include the special named arguments for setting query clauses.
``find('byCategoryOrUser', userId: $somevar, conditions: ['enabled' => true])``.

Http
----

Expand All @@ -267,4 +311,3 @@ TestSuite
---------

- ``IntegrationTestTrait::requestAsJson()`` has been added to set JSON headers for the next request.

8 changes: 4 additions & 4 deletions en/controllers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -414,10 +414,10 @@ The ``fetchTable()`` function comes handy when you need to use a table that is n
the controller's default one::

// In a controller method.
$recentArticles = $this->fetchTable('Articles')->find('all', [
'limit' => 5,
'order' => 'Articles.created DESC'
])
$recentArticles = $this->fetchTable('Articles')->find('all',
limit: 5,
order: 'Articles.created DESC'
)
->all();

Paginating a Model
Expand Down
2 changes: 1 addition & 1 deletion en/controllers/components/authentication.rst
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ In the example shown below the query is modified to fetch only required fields
and add a condition. You must ensure that you select the fields you need to
authenticate a user, such as ``username`` and ``password``::

public function findAuth(\Cake\ORM\Query\SelectQuery $query, array $options)
public function findAuth(\Cake\ORM\Query\SelectQuery $query)
{
$query
->select(['id', 'username', 'password'])
Expand Down
12 changes: 5 additions & 7 deletions en/controllers/pagination.rst
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ as values for the finder::
// Our custom finder is called findTagged inside ArticlesTable.php
// which is why we're using `tagged` as the key.
// Our finder should look like:
// public function findTagged(Query $query, array $options) {
// public function findTagged(Query $query, array $tagged = [])
$settings = [
'finder' => [
'tagged' => $customFinderOptions
Expand Down Expand Up @@ -189,9 +189,8 @@ need to define an alias for the model.::
];

$publishedArticles = $this->paginate(
$this->Articles->find('all', [
'scope' => 'published_articles'
])->where(['published' => true])
$this->Articles->find('all', scope: 'published_articles')
->where(['published' => true])
);

// Load an additional table object to allow differentiating in the paginator
Expand All @@ -202,9 +201,8 @@ need to define an alias for the model.::
]);

$unpublishedArticles = $this->paginate(
$unpublishedArticlesTable->find('all', [
'scope' => 'unpublished_articles'
])->where(['published' => false])
$unpublishedArticlesTable->find('all', scope: 'unpublished_articles')
->where(['published' => false])
);

.. _control-which-fields-used-for-ordering:
Expand Down
8 changes: 3 additions & 5 deletions en/development/testing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -834,11 +834,12 @@ Let's say we already have our Articles Table class defined in

class ArticlesTable extends Table
{
public function findPublished(SelectQuery $query, array $options): SelectQuery
public function findPublished(SelectQuery $query): SelectQuery
{
$query->where([
$this->alias() . '.published' => 1
]);

return $query;
}
}
Expand Down Expand Up @@ -997,10 +998,7 @@ controller code looks like::
}
}
if (!empty($short)) {
$result = $this->Articles->find('all', [
'fields' => ['id', 'title']
])
->all();
$result = $this->Articles->find('all', fields: ['id', 'title'])->all();
} else {
$result = $this->Articles->find()->all();
}
Expand Down
4 changes: 2 additions & 2 deletions en/orm/associations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -709,8 +709,8 @@ such as a where condition by designating the through table name before the field
you are filtering on::

$query = $this->find(
'list',
['valueField' => 'studentFirstName', 'order' => 'students.id']
'list',
valueField: 'studentFirstName', order: 'students.id'
)
->contain(['Courses'])
->matching('Courses')
Expand Down
6 changes: 3 additions & 3 deletions en/orm/behaviors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,14 @@ a finder method so we can fetch articles by their slug. Behavior finder
methods, use the same conventions as :ref:`custom-find-methods` do. Our
``find('slug')`` method would look like::

public function findSlug(SelectQuery $query, array $options)
public function findSlug(SelectQuery $query, string $slug): SelectQuery
{
return $query->where(['slug' => $options['slug']]);
return $query->where(['slug' => $slug]);
}

Once our behavior has the above method we can call it::

$article = $articles->find('slug', ['slug' => $value])->first();
$article = $articles->find('slug', slug: $value)->first();

Limiting or Renaming Exposed Finder Methods
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
8 changes: 3 additions & 5 deletions en/orm/behaviors/translate.rst
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ use TranslateBehavior with ``find('list')``::
[1 => 'Mi primer artículo', 2 => 'El segundo artículo', 15 => 'Otro articulo' ...]

// Change the locale to french for a single find call
$data = $this->Articles->find('list', ['locale' => 'fr'])->toArray();
$data = $this->Articles->find('list', locale: 'fr')->toArray();

Retrieve All Translations For An Entity
---------------------------------------
Expand Down Expand Up @@ -290,9 +290,7 @@ Limiting the Translations to be Retrieved
You can limit the languages that are fetched from the database for a particular
set of records::

$results = $this->Articles->find('translations', [
'locales' => ['en', 'es']
]);
$results = $this->Articles->find('translations', locales: ['en', 'es']);
$article = $results->first();
$spanishTranslation = $article->translation('es');
$englishTranslation = $article->translation('en');
Expand Down Expand Up @@ -366,7 +364,7 @@ to call the method on each table, for example::
$this->Articles->setLocale('es');
$this->Articles->Categories->setLocale('es');

$data = $this->Articles->find('all', ['contain' => ['Categories']]);
$data = $this->Articles->find('all', contain: ['Categories']);

This example also assumes that ``Categories`` has the TranslateBehavior attached
to it.
Expand Down
32 changes: 15 additions & 17 deletions en/orm/behaviors/tree.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ Getting direct descendents

Getting a flat list of the descendants for a node can be done with::

$descendants = $categories->find('children', ['for' => 1]);
$descendants = $categories->find('children', for: 1);

foreach ($descendants as $category) {
echo $category->name . "\n";
Expand All @@ -77,7 +77,7 @@ Getting a flat list of the descendants for a node can be done with::
If you need to pass conditions you do so as per normal::

$descendants = $categories
->find('children', ['for' => 1])
->find('children', for: 1)
->where(['name LIKE' => '%Foo%'])
->all();

Expand All @@ -89,15 +89,15 @@ If you instead need a threaded list, where children for each node are nested
in a hierarchy, you can stack the 'threaded' finder::

$children = $categories
->find('children', ['for' => 1])
->find('children', for: 1)
->find('threaded')
->toArray();

foreach ($children as $child) {
echo "{$child->name} has " . count($child->children) . " direct children";
}

While, if youre using custom ``parent_id`` you need to pass it in the
While, if you're using custom ``parent_id`` you need to pass it in the
'threaded' finder option (i.e. ``parentField``) .

.. note::
Expand Down Expand Up @@ -143,21 +143,19 @@ The ``treeList`` finder takes a number of options:

An example of all options in use is::

$query = $categories->find('treeList', [
'keyPath' => 'url',
'valuePath' => 'id',
'spacer' => ' '
]);
$query = $categories->find('treeList',
keyPath: 'url',
valuePath: 'id',
spacer: ' '
);

An example using closure::

$query = $categories->find('treeList', [
'keyPath' => 'url',
'valuePath' => function($entity){
$query = $categories->find('treeList',
valuePath: function($entity){
return $entity->url . ' ' . $entity->id
},
'spacer' => ' '
]);
}
);

Finding a path or branch in the tree
------------------------------------
Expand All @@ -167,7 +165,7 @@ of the tree. This is useful, for example, for adding the breadcrumbs list for
a menu structure::

$nodeId = 5;
$crumbs = $categories->find('path', ['for' => $nodeId])->all();
$crumbs = $categories->find('path', for: $nodeId)->all();

foreach ($crumbs as $crumb) {
echo $crumb->name . ' > ';
Expand Down Expand Up @@ -322,7 +320,7 @@ The deletion of a node is based off of the ``lft`` and ``rght`` values of the en
is important to note when looping through the various children of a node for
conditional deletes::

$descendants = $teams->find('children', ['for' => 1])->all();
$descendants = $teams->find('children', for: 1)->all();

foreach ($descendants as $descendant) {
$team = $teams->get($descendant->id); // search for the up-to-date entity object
Expand Down
Loading