Cakephp 3 dynamically build contain

2k views Asked by At

How can I dynamically build the contain in the new cakephp 3 query builder. This is what I have now:

$query = $dbTable->find()
                ->select($contain['select']['fields'])
                ->contain(function($q) use($array,$contain){
                      $new = [];
                      foreach($array as $v){
                        if(isset($contain['contains'][$v])){
                          $fields = $contain['contains'][$v];
                          $new[$v] = $q->select($fields);
                         }
                      }
                      return $new;
                  });

But I am getting several errors with this:

Warning (2): Illegal offset type in isset or empty [CORE\src\ORM\EagerLoader.php, line 198]
Warning (2): strpos() expects parameter 1 to be string, object given [CORE\src\ORM\EagerLoader.php, line 203]
Warning (2): Illegal offset type [CORE\src\ORM\EagerLoader.php, line 223]
Warning (2): Illegal offset type [CORE\src\ORM\EagerLoader.php, line 224]
3

There are 3 answers

0
ndm On BEST ANSWER

As already mentioned by Lorenzo, that's not how it works, contain() doesn't accept callables, just look at the docs:

http://api.cakephp.org/3.0/class-Cake.ORM.Query.html#_contain

Also your code would invoke select() multiple times on one and the same query, that wouldn't work anyways.

However, looking at your code it seems that you could simply make use of the fields option, ie build a simple array to pass to contain(). This is shown in the docs, the example however will trigger an error as it seems to be necessary to explicitly set the foreign key field too:

$query->contain([
    'Articles' => [
        'fields' => ['foreign_key_column_name', 'title']
    ]
]);
0
José Lorenzo Rodríguez On

You cannot use contain with a closure inside. If you believe this is a good idea (I think it could be) then open a enhancement request on github.

0
Bruny On

To get all fields in the table Articles do this in your controller.

$query = $this->modelName->find('all')
                   ->contain('Articles');

If you want a expecify field use this:

$query = $this->modelName->find('list', [
    'keyField' => 'id',
    'valueField' => 'author.name'
])->contain(['Articles']);

To more informations about: https://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html