3.7.3.1 find
find($type, $params)
Find is the multifunctional workhorse of all model data-retrieval functions. $type can be either 'all', 'first', 'count', 'list', 'neighbors' or 'threaded'. The default find type is 'first'. Keep in mind that $type is case sensitive. Using a upper case character (for example 'All') will not produce the expected results.
$params is used to pass all parameters to the various finds, and has the following possible keys by default—all of which are optional:
array(
'conditions' => array('Model.field' => $thisValue), //array of conditions
'recursive' => 1, //int
'fields' => array('Model.field1', 'DISTINCT Model.field2'), //array of field names
'order' => array('Model.created', 'Model.field3 DESC'), //string or array defining order
'joins' => array(), // array of arrays defining join operations
'group' => array('Model.field'), //fields to GROUP BY
'limit' => n, //int
'page' => n, //int
'offset'=> n, //int
'callbacks' => true //other possible values are false, 'before', 'after'
) array('conditions' => array('Model.field' => $thisValue), //array of conditions'recursive' => 1, //int'fields' => array('Model.field1', 'DISTINCT Model.field2'), //array of field names'order' => array('Model.created', 'Model.field3 DESC'), //string or array defining order'joins' => array(), // array of arrays defining join operations'group' => array('Model.field'), //fields to GROUP BY'limit' => n, //int'page' => n, //int'offset'=> n, //int'callbacks' => true //other possible values are false, 'before', 'after')
It's also possible to add and use other parameters, as is made use of by some find types, behaviors and of course possible with your own model methods
More information about model callbacks is available here. For details about join options, see Joining tables.
3.7.3.1.1 find('first')
find('first', $params)
'first' is the default find type, and will return one result, you'd use this for any use where you expect only one result. Below are a couple of simple (controller code) examples:
function some_function() {
...
$this->Article->order = null; // resetting if it's set
$semiRandomArticle = $this->Article->find();
$this->Article->order = 'Article.created DESC'; // simulating the model having a default order
$lastCreated = $this->Article->find();
$alsoLastCreated = $this->Article->find('first', array('order' => array('Article.created DESC')));
$specificallyThisOne = $this->Article->find('first', array('conditions' => array('Article.id' => 1)));
...
}
function some_function() {...$this->Article->order = null; // resetting if it's set$semiRandomArticle = $this->Article->find();$this->Article->order = 'Article.created DESC'; // simulating the model having a default order$lastCreated = $this->Article->find();$alsoLastCreated = $this->Article->find('first', array('order' => array('Article.created DESC')));$specificallyThisOne = $this->Article->find('first', array('conditions' => array('Article.id' => 1)));...}
In the first example, no parameters at all are passed to find - therefore no conditions or sort order will be used. The format returned from find('first') call is of the form:
Array
(
[ModelName] => Array
(
[id] => 83
[field1] => value1
[field2] => value2
[field3] => value3
)
[AssociatedModelName] => Array
(
[id] => 1
[field1] => value1
[field2] => value2
[field3] => value3
)
)
There are no additional parameters used by find('first').
3.7.3.1.2 find('count')
find('count', $params)
find('count', $params) returns an integer value. Below are a couple of simple (controller code) examples:
function some_function() {
...
$total = $this->Article->find('count');
$pending = $this->Article->find('count', array('conditions' => array('Article.status' => 'pending')));
$authors = $this->Article->User->find('count');
$publishedAuthors = $this->Article->find('count', array(
'fields' => 'COUNT(DISTINCT Article.user_id) as count',
'conditions' => array('Article.status !=' => 'pending')
));
...
}
function some_function() {...$total = $this->Article->find('count');$pending = $this->Article->find('count', array('conditions' => array('Article.status' => 'pending')));$authors = $this->Article->User->find('count');$publishedAuthors = $this->Article->find('count', array('fields' => 'COUNT(DISTINCT Article.user_id) as count','conditions' => array('Article.status !=' => 'pending')));...}
Don't pass fields as an array to find('count'). You would only need to specify fields for a DISTINCT count (since otherwise, the count is always the same - dictated by the conditions).
There are no additional parameters used by find('count').
3.7.3.1.3 find('all')
find('all', $params)
find('all') returns an array of (potentially multiple) results. It is in fact the mechanism used by all find() variants, as well as paginate. Below are a couple of simple (controller code) examples:
function some_function() {
...
$allArticles = $this->Article->find('all');
$pending = $this->Article->find('all', array('conditions' => array('Article.status' => 'pending')));
$allAuthors = $this->Article->User->find('all');
$allPublishedAuthors = $this->Article->User->find('all', array('conditions' => array('Article.status !=' => 'pending')));
...
}
function some_function() {...$allArticles = $this->Article->find('all');$pending = $this->Article->find('all', array('conditions' => array('Article.status' => 'pending')));$allAuthors = $this->Article->User->find('all');$allPublishedAuthors = $this->Article->User->find('all', array('conditions' => array('Article.status !=' => 'pending')));...}
In the above example $allAuthors will contain every user in the users table, there will be no condition applied to the find as none were passed.
The results of a call to find('all') will be of the following form:
Array
(
[0] => Array
(
[ModelName] => Array
(
[id] => 83
[field1] => value1
[field2] => value2
[field3] => value3
)
[AssociatedModelName] => Array
(
[id] => 1
[field1] => value1
[field2] => value2
[field3] => value3
)
)
)
There are no additional parameters used by find('all').
3.7.3.1.4 find('list')
find('list', $params)
find('list', $params) returns an indexed array, useful for any use where you would want a list such as for populating input select boxes. Below are a couple of simple (controller code) examples:
function some_function() {
...
$allArticles = $this->Article->find('list');
$pending = $this->Article->find('list', array(
'conditions' => array('Article.status' => 'pending')
));
$allAuthors = $this->Article->User->find('list');
$allPublishedAuthors = $this->Article->find('list', array(
'fields' => array('User.id', 'User.name'),
'conditions' => array('Article.status !=' => 'pending'),
'recursive' => 0
));
...
}
function some_function() {...$allArticles = $this->Article->find('list');$pending = $this->Article->find('list', array('conditions' => array('Article.status' => 'pending')));$allAuthors = $this->Article->User->find('list');$allPublishedAuthors = $this->Article->find('list', array('fields' => array('User.id', 'User.name'),'conditions' => array('Article.status !=' => 'pending'),'recursive' => 0));...}
In the above example $allAuthors will contain every user in the users table, there will be no condition applied to the find as none were passed.
The results of a call to find('list') will be in the following form:
Array
(
//[id] => 'displayValue',
[1] => 'displayValue1',
[2] => 'displayValue2',
[4] => 'displayValue4',
[5] => 'displayValue5',
[6] => 'displayValue6',
[3] => 'displayValue3',
)
When calling find('list') the fields passed are used to determine what should be used as the array key, value and optionally what to group the results by. By default the primary key for the model is used for the key, and the display field (which can be configured using the model attribute displayField) is used for the value. Some further examples to clarify:.
function some_function() {
...
$justusernames = $this->Article->User->find('list', array('fields' => array('User.username')));
$usernameMap = $this->Article->User->find('list', array('fields' => array('User.username', 'User.first_name')));
$usernameGroups = $this->Article->User->find('list', array('fields' => array('User.username', 'User.first_name', 'User.group')));
...
}
function some_function() {...$justusernames = $this->Article->User->find('list', array('fields' => array('User.username')));$usernameMap = $this->Article->User->find('list', array('fields' => array('User.username', 'User.first_name')));$usernameGroups = $this->Article->User->find('list', array('fields' => array('User.username', 'User.first_name', 'User.group')));...}
With the above code example, the resultant vars would look something like this:
$justusernames = Array
(
//[id] => 'username',
[213] => 'AD7six',
[25] => '_psychic_',
[1] => 'PHPNut',
[2] => 'gwoo',
[400] => 'jperras',
)
$usernameMap = Array
(
//[username] => 'firstname',
['AD7six'] => 'Andy',
['_psychic_'] => 'John',
['PHPNut'] => 'Larry',
['gwoo'] => 'Gwoo',
['jperras'] => 'Joël',
)
$usernameGroups = Array
(
['User'] => Array
(
['PHPNut'] => 'Larry',
['gwoo'] => 'Gwoo',
)
['Admin'] => Array
(
['_psychic_'] => 'John',
['AD7six'] => 'Andy',
['jperras'] => 'Joël',
)
)
3.7.3.1.5 find('threaded')
find('threaded', $params)
find('threaded', $params) returns a nested array, and is appropriate if you want to use the parent_id field of your model data to build nested results. Below are a couple of simple (controller code) examples:
function some_function() {
...
$allCategories = $this->Category->find('threaded');
$aCategory = $this->Category->find('first', array('conditions' => array('parent_id' => 42))); // not the root
$someCategories = $this->Category->find('threaded', array(
'conditions' => array(
'Article.lft >=' => $aCategory['Category']['lft'],
'Article.rght <=' => $aCategory['Category']['rght']
)
));
...
}
function some_function() {...$allCategories = $this->Category->find('threaded');$aCategory = $this->Category->find('first', array('conditions' => array('parent_id' => 42))); // not the root$someCategories = $this->Category->find('threaded', array('conditions' => array('Article.lft >=' => $aCategory['Category']['lft'],'Article.rght <=' => $aCategory['Category']['rght'])));...}
It is not necessary to use the Tree behavior to use this method - but all desired results must be possible to be found in a single query.
In the above code example, $allCategories will contain a nested array representing the whole category structure. The second example makes use of the data structure used by the Tree behavior the return a partial, nested, result for $aCategory and everything below it. The results of a call to find('threaded') will be of the following form:
Array
(
[0] => Array
(
[ModelName] => Array
(
[id] => 83
[parent_id] => null
[field1] => value1
[field2] => value2
[field3] => value3
)
[AssociatedModelName] => Array
(
[id] => 1
[field1] => value1
[field2] => value2
[field3] => value3
)
[children] => Array
(
[0] => Array
(
[ModelName] => Array
(
[id] => 42
[parent_id] => 83
[field1] => value1
[field2] => value2
[field3] => value3
)
[AssociatedModelName] => Array
(
[id] => 2
[field1] => value1
[field2] => value2
[field3] => value3
)
[children] => Array
(
)
)
...
)
)
)
The order results appear can be changed as it is influence by the order of processing. For example, if 'order' => 'name ASC' is passed in the params to find('threaded'), the results will appear in name order. Likewise any order can be used, there is no inbuilt requirement of this method for the top result to be returned first.
There are no additional parameters used by find('threaded').
3.7.3.1.6 find('neighbors')
find('neighbors', $params)
'neighbors' will perform a find similar to 'first', but will return the row before and after the one you request. Below is a simple (controller code) example:
function some_function() {
$neighbors = $this->Article->find('neighbors', array('fields' => 'id', 'value' => 3));
}
function some_function() {$neighbors = $this->Article->find('neighbors', array('fields' => 'id', 'value' => 3));}
You can see in this example the two required elements of the $params array: field and value. Other elements are still allowed as with any other find (Ex: If your model acts as containable, then you can specify 'contain' in $params). The format returned from a find('neighbors') call is in the form:
Array
(
[prev] => Array
(
[ModelName] => Array
(
[id] => 2
[field1] => value1
[field2] => value2
...
)
[AssociatedModelName] => Array
(
[id] => 151
[field1] => value1
[field2] => value2
...
)
)
[next] => Array
(
[ModelName] => Array
(
[id] => 4
[field1] => value1
[field2] => value2
...
)
[AssociatedModelName] => Array
(
[id] => 122
[field1] => value1
[field2] => value2
...
)
)
)
Note how the result always contains only two root elements: prev and next.
