简体   繁体   中英

Is it possible to use find('list') with Containable behavior in CakePHP 3?

Application is using CakePHP version 3.5.18

I have used the ORM to obtain a list which returns key/value pairs:

$Displays = TableRegistry::get('Displays');
$displays = $Displays->find('list', ['keyField' => 'id', 'valueField' => 'id'])->where(...)->toArray();

This works as expected. An example of debug($displays); looks like this:

(int) 36 => (int) 36,
(int) 160 => (int) 160,
(int) 149 => (int) 149,
...

In this particular application there are 3 Models which work in the following hierarchy:

  • Regulations (Level 1. Table name regulations )
    • Groups (Level 2. Table name groups )
      • Displays (Level 3. Table name displays )

The application has been baked so that the appropriate relationships are defined in the Table classes.

// src/Model/Table/RegulationsTable.php
$this->hasMany('Groups', [
    'foreignKey' => 'regulation_id'
]);

// src/Model/Table/GroupsTable.php
$this->hasMany('Displays', [
    'foreignKey' => 'group_id'
]);

// src/Model/Table/DisplaysTable.php
$this->belongsTo('Groups', [
    'foreignKey' => 'group_id',
    'joinType' => 'INNER'
]);

What I want to do is adjust the query defined by $displays so that the results correspond to a given array of Regulations.id . The vanilla SQL equivalent of what I'm trying to do is ... WHERE regulations.id IN (1,2,3) assuming the ID's were 1, 2 and 3.

When I read the Cake docs on Passing conditions to contain it says:

When you limit the fields that are fetched from an association, you must ensure that the foreign key columns are selected. Failing to select foreign key fields will cause associated data to not be present in the final result.

I don't understand how this is possible with find('list') because that only selects the keyField and valueField specified by the developer? In this case that would be displays.id for both.

In any case I don't understand how to write this query because in the same linked documentation it says

When using contain() you are able to restrict the data returned by the associations and filter them by conditions. To specify conditions, pass an anonymous function that receives as the first argument a query object, \\Cake\\ORM\\Query

What would the contain() actually operate on: I assume it's Regulations but don't know how to write this.

I think you need to look at filtering data by matching, not through contains. (If I understand correctly.)

You can combine find('list') with ->matching(...) :

$displays = $this->Displays->find('list')
    ->matching('Groups.Regulations', function ($q) use ($ids) {
        return $q->where(['Regulations.id IN' => $ids]);
    })
    ->toArray();

(Still untested)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM