Метод поиска списка CakePHP не возвращает массив, как ожидалось - PullRequest
0 голосов
/ 11 мая 2018

Я использую метод поиска Cake $table->find('list'), чтобы получить массив связанных пользователей [id => name]. Использовали это в прошлом, и это работало хорошо. В этой находке я храню таблицу ownToMany и получаю [id => name].

В \App\Model\Table\SitesTable::initialize определено отношение ClientUsersWithAuthoritiesToMany

$this->belongsToMany('ClientUsersWithAuthorities', [
  'className'        => 'AppUsers',
  'joinTable'        => 'sites_client_users',
  'foreignKey'       => 'site_id',
  'targetForeignKey' => 'user_id',
  'propertyName'     => 'client_users_with_authorities']);

В \App\Controller\ClientGroupsController::getClientgroupUsers

$siteClientUsers = $this->Sites->find('list', [
  'keyField'   => 'client_users_with_authorities.id',
  'valueField' => 'client_users_with_authorities.full_name'])
->where(['id' => $siteId])
->contain(['ClientUsersWithAuthorities'])
->toArray();

$ siteClientUsers возвращает [0 => null] вместо [1234 => 'Client 1 name', 5678 => 'Client 2 name'], как ожидалось. Оба пользователя существуют в объединительной таблице.

Три других метода (ниже) возвращают массив, который я ищу и который я ожидаю $this->Sites->find('list'), чтобы произвести. Поваренная книга описывает связанные данные могут быть перечислены. https://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html#finding-key-value-pairs

Так почему же $this->Sites->find('list') не создает ожидаемый массив?

MapReduce

$mapper = function ($data, $key, $mapReduce) {
if (!empty($data['client_users_with_authorities'])) {
    foreach ($data['client_users_with_authorities'] as $user) {
        $mapReduce->emit($user);
    }}};
$siteClientUsers = $this->Sites->find('list', [
    'keyField'   => 'id',
    'valueField' => 'full_name'])
->where(['id' => $siteId])
->contain(['ClientUsersWithAuthorities'])
->mapReduce($mapper)
->toArray();

Hash :: скомбинировать

$siteClientUsers = $this->Sites->find('all')
->where(['id' => $siteId])
->contain(['ClientUsersWithAuthorities'])
->toArray();
$siteClientUsers  = Hash::combine($siteClientUsers,'{n}.client_users_with_authorities.{n}.id', '{n}.client_users_with_authorities.{n}.full_name');

Temp относится к отношениям в таблице соединений

$table = $this->getTableLocator()->get('SitesClientUsers');
$table->belongsTo('Users', [
'className'   => 'AppUsers',
'foreign_key' => 'user_id']);
$siteClientUsers =  $table->find('list', [
    'keyField' => 'Users.id',
    'valueField' => 'Users.full_name'
])
->select(['Users.id', 'Users.full_name'])
->where(['SitesClientUsers.site_id' => $siteId])
->contain(['Users'])
->toArray();

1 Ответ

0 голосов
/ 11 мая 2018

Поваренная книга говорит:

Вы также можете создавать списки данных из ассоциаций, которые могут быть достигнуты с помощью объединений

Важной частью является ", которая может быть достигнута объединениями ", что не относится к belongsToMany ассоциациям. Учитывая, что преобразование списка происходит на уровне PHP, описание, возможно, должно сосредоточиться на этом, но оно все еще остается в силе.

client_users_with_authorities будет массивом, т.е., возможно, несколькими записями, поэтому вы не можете использовать его для заполнения родительской записи - одна запись Sites представляет одну запись списка. Если вы хотите найти список ClientUsersWithAuthorities, который принадлежит определенному сайту, то вы можете использовать одно из ваших других решений (или что-то подобное), или вы можете, например, запросить с другой стороны ассоциации и используйте совпадение на Sites:

$query = $this->Sites->ClientUsersWithAuthorities
    ->find('list', [
        'keyField' => 'id',
        'valueField' => 'full_name'
    ])
    ->matching('Sites', function (\Cake\ORM\Query $query) use ($siteId) {
        return $query->where([
            'Sites.id' => $siteId
        ]);
    })
    ->group('ClientUsersWithAuthorities.id');

Это создаст объединения на основе Sites.id, так что вы получите только ClientUsersWithAuthorities, связанные с Sites, где Sites.id соответствует $siteId.

Смотри также

...