This is the case.
MODEL
User hasOne Info
User
id
username
password
manager_id
Info
id
first_name
last_name
sex
I wanted to generate a list of all Users displaying the first_name, last_name and sex. And I wanted the indexes to be generated with User.id and the display field with this format "Info.last_name, Info.first_name (Info.sex)". I have developed a function to override cakePHP $model->find.
In your app_model.php, you include this function:
class AppModel extends Model {
function find($type, $options = array()) {
switch ($type) {
case 'superlist':
if(!isset($options['format'])) {
$options['format'] = '';
for ($i=0; $i$options['format'] .= "%$i ";
}
$options['format'] = trim($options['format']);
}
if (isset($options['index'])){
preg_match('/(.*?)\.(.*)/', $options['index'], $match);
$index_alias = $match[1];
$index_field = $match[2];
}else{
$index_alias = $this->alias;
$index_field = 'id';
}
$options['fields'] = array_merge(array("{$index_alias}.{$index_field}"), $options['fields']);
$list = $this->find('all', $options);
$result = array();
foreach ($list as $row){
$result[$row[$index_alias][$index_field]] = $options['format'];
foreach ($options['fields'] as $index=>$field){
preg_match('/(.*?)\.(.*)/', $field, $match);
$field_alias = $match[1];
$field_field = $match[2];
$result[$row[$index_alias][$index_field]] =
str_replace('%'.$index, $row[$field_alias][$field_field],
$result[$row[$index_alias][$index_field]]);
}
}
return $result;
break;
default:
return parent::find($type, $options);
break;
}
}
}
This is how you call the generate list function in your controller action.
// if you have not declared hasOne Info in User model, this is needed in order for User model generate Info model with it and you can pass condition on Info fields
$this->User->bindModel(
array(
'hasOne' => array('Info')
)
);
$users = $this->User->find('superlist',
array(
'format' => '%3, %2 (%1)',
'index' => 'User.id', // --> this is the default so you may not pass this option
'fields' =>
array(
'Info.sex', // --> %1
'Info.first_name', // --> %2
'Info.last_name', // --> %3
),
'order' => "Info.first_name, Info.last_name", // -- if you want to sort the option
'condition' => "User.manager_id=2 AND Info.lastname='Smith'", // --> if you need some filtering
)
);
$this->set(compact('users'));
$users array will contain the following structure:
array(
'User.id1' => 'Info.last_name1, Info.first_name1 (Info.sex1)',
'User.id2' => 'Info.last_name2, Info.first_name2 (Info.sex2)',
'User.id3' => 'Info.last_name3, Info.first_name3 (Info.sex3)',
.
.
.
'User.idN' => 'Info.last_nameN, Info.first_nameN (Info.sexN)',
)
Hope this post can help you in your future cakePHP 1.2 development.
Thanks to http://teknoid.wordpress.com/2008/09/04/findlist-with-three-or-combined-fields/ for giving me inspiration to develop this function.
6 comments:
Thanks to share you valuable knowledge.
This was a great solution, thanks for sharing! This kind of thing is such a common use case that there's no excuse for it not to have been in core from day 1.
This is really useful as at the momment building your datasets in the controller seems a little un-mvc.
Doing it the way you explain in your article is a much better method.
@all
Glad this code helps you.
Great read Owen. Thanks for sharing!
PHP Programmer
This is knowledgeable site.
Post a Comment