Friday 17 April 2009
Facebook StumbleUpon Twitter Google+ Pin It

CakePHP 1.2 Versatile Model find('list')

Have you wanted to generate a list of options for your select but wanted the display field to be generated dynamically instead of using cakePHP find('list')?
This is the case.
MODEL
User hasOne Info

User id 
username 
password 
manager_id 
Info id 
first_name 
last_name 
email 
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.

Parthiv Patel
Bhaishri Info Solution
Sr. PHP Developer
Limdi Chowk, AT PO. Nar, Di. Anand
Nar, Gujarat
388150
India
pparthiv2412@gmail.com
7383343029
DOB: 12/24/1986

No comments: