Может ли псевдоним запроса использовать предложение содержимого? - PullRequest
0 голосов
/ 26 октября 2019

Я использую объединение, чтобы объединить два набора данных, а затем следующий запрос, чтобы правильно настроить нумерацию страниц

$paginationQuery = $this->find('all')
    ->contain(['EmailAddresses' => [
        'foreignKey' => false,
        'queryBuilder' => function($q) {
                  return $q->where(['Members__id' => 'EmailAddresses.member_id']);
                 }
        ]])
        ->select( $selectMainUnion )
        ->from([$this->getAlias() => $query])
        ->order(['Members__last_name' => 'ASC', 'Members__first_name' => 'ASC']);

Я также попытался

$paginationQuery = $this->find('all')
        ->contain(['EmailAddresses'])
        ->select( $selectMainUnion )
        ->from([$this->getAlias() => $query])
        ->order(['Members__last_name' => 'ASC', 'Members__first_name' => 'ASC']);

и пробовал $ query-> loadInto($ query, ['EmailAddresses']);где $ query является результатом объединения.

Ни один из этих результатов не приводит к добавлению адресов электронной почты в $ paginationQuery.

Есть ли способ сделать это?

Добавление куточнить код

$selectMain =['Members.id',
    'Members.member_type',
    'Members.first_name',
    'Members.middle_name',
    'Members.last_name',
    'Members.suffix',
    'Members.date_joined'];

foreach($selectMain as $select) {
    $selectMainUnion[] = str_replace('.', '__', $select);
}

$this->hasMany('EmailAddresses', [
   'foreignKey' => 'member_id',
   'dependent' => true,
]);

Если посмотреть на SQL в журнале SQL DebugKit, нет ссылки на таблицу EmailAddresses.

1 Ответ

0 голосов
/ 26 октября 2019

Обычно контейнеры работают нормально, независимо от условия запроса FROM, не важно, является ли это таблица или подзапрос. Однако для того, чтобы это работало, требуется, чтобы были выбраны обязательные поля первичного и / или внешнего ключа и чтобы они были в правильном формате.

По умолчанию ORM-запросы CakePHP автоматически присваивают псевдонимы выбранным полям, т.е. выбирается как Alias.field AS Alias__field. Поэтому, когда Alias является подзапросом, тогда Alias.field не существует, вам придется выбрать Alias.Alias__field. Таким образом, при использовании автоматических псевдонимов ваш выбор Members__id будет преобразован в Members.Members__id AS Members__Members__id, а Members__Members__id - это не то, что понимает ORM, в конечном итоге он будет иметь значение Members__id в ваших объектах, где ожидающий загрузчик будет ожидать *Вместо 1012 *, то есть имени первичного ключа, который используется для внедрения результатов запрашиваемых hasMany связанных записей (это происходит в отдельном запросе), ваш пользовательский queryBuilder не поможет с этим, так как внедрениепроисходит потом на уровне PHP.

Короче говоря, чтобы исправить проблему, вы можете изменить способ выбора полей запросов на объединение, т. е. убедиться, что они не выбраны с псевдонимами, таким образом, запрос на разбиение на страницыполя не должны быть изменены вообще:

$fields = $table->getSchema()->columns();
$fields = array_combine($fields, $fields);

$query->select($fields);

Это создаст список полей в формате ['id' => 'id', ...], выглядит немного странно, но это работает (до тех пор, пока нет двусмысленности, потому чтонапример, из соединенных таблиц) SQL будет выглядеть как id AS id, поэтому ваш запрос нумерации страниц может просто ссылаться на поля типа Members.id.

Другим способом было бы выбрать псевдонимы подзапроса, то есть не просто выбрать Member__id, который ORM превращает в Member__Member__id при применении автоматического псевдонима, а использовать Members.Member__id, например:

[
    'Member__id' => 'Members.Member__id',
    // ...
]

Таким образом, никакого автоматического псевдонима не происходит, на уровне SQL будет выбрано поле, подобное Members.Member__id AS Member__id, и поле будет иметь значение id в ваших сущностях, которое загрузчик найдет и сможет использоватьдля введения связанных записей.

...