Posts Tagged ‘ containable ’

find(‘list’) and Containable

As you must know, when calling $this->Model->find(‘list’) passing a contain parameter, it won’t take effect, and you won’t be able to do something like:


$workers = $this->Worker->Person->find(
    'list',
    array(
        'fields' => array('Worker.id', 'Person.name')
        'contain' => array(
            'Worker',
            'PersonType' => array(
                'conditions' => array('PersonType.type' => 'Worker')
            )
        )
    )
);

a solution for this problem would be something like this:


$workers = $this->Worker->Person->find(
    'all',
    array(
        'fields' => array('Worker.id', 'Person.name')
        'contain' => array(
            'Worker',
            'PersonType' => array(
                'conditions' => array('PersonType.type' => 'Worker')
            )
        )
    )
);
$workers = Set::combine($workers, '{n}.Worker.id', '{n}.Person.id'')

Well.. it’s not bad at all, but we could get a better solution – we could create a custom find type for a find list with Containable support!
We’ll be following the Matt Curry’s custom find method published in it’s awesome CakePHP e-book.

So, at first you must download Matt Curry’s find plugin vendor’s folder, put it under your app’s plugin/find/ folder, you should create the find folder.
Then in your app’s app_model.php you should import the find_app_model.php vendor file, and your AppModel class would extends FindAppModel, this would include some initial setup done for custom find methods. Now you just add our __findListContainable() method to it, it defines our custom find list method.
And you will end up with an AppModel like this:

App::import('Vendor', 'Find.find_app_model');

class AppModel extends FindAppModel {

    public $actsAs = array('Containable');

    public function __findListContainable($options) {
        $default_fields = array("{$this->alias}.{$this->primaryKey}", "{$this->alias}.{$this->displayField}", null);
        if(!empty($options['fields'])) {
            $fields = $default_fields + $options['fields'];
            unset($options['fields']);
        } else {
            $fields = $default_fields;
        }
        $results = $this->find('all', $options);
        foreach($fields as $key => $field) {
            if(!empty($field)) {
                $fields[$key] = '{n}.'.$field;
            }
        }
        return Set::combine($results, $fields[0], $fields[1], $fields[2]);
    }

}

Ok, now you can do any find list with containable parameters with no problems like the Worker’s example above.

Have fun!

Advertisements