«Через» связь с «Foreign_key» & amp; ‘модельные’ поля в CakePHP 3

Это довольно стандартная вещь, которую я делал, вероятно, 600 раз в CakePHP 2, но я не могу заставить ее работать в CakePHP 3.

я имею Videos, Photos, Articles, у меня тоже есть Categories,

Видео, фотографии и статьи могут принадлежать к одной или нескольким категориям.

Цель текущей проблемы — вытащить видео из определенной категории.

Итак, я попробовал это:

// VideosTable
$this->belongsToMany('Categories', [
'joinTable' => 'categorized',
'className' => 'Categorized',
'foreignKey' => 'foreign_key',
'conditions' => [
'Categorized.model' => 'Videos',
]
]);

public function getTopVideosByCategory($categorySlug)
{
return $this->Categories->find('all')
->where(['Categories.slug' => $categorySlug])
->contain([
'Videos' => function ($q) {
return $q
->limit(8)
->contain([
'Tags',
'Categories' // tried with and without this
])
->order([
'Videos.featured' => 'DESC',
'Videos.created' => 'DESC'
]);
}
])
->first();
}

Ошибка: SQLSTATE [42S22]: столбец не найден: 1054 неизвестный столбец
«Категоризованный.модель» в «где пункт»

Я пробовал ряд других способов, включая создание модели таблицы соединений, и несколько других, но продолжаю получать ошибки. Я пробовал с каждым вариантом и с ограниченным количеством вариантов. Я попытался использовать реальный класс Table, и я попробовал псевдо-класс (например, «Категоризованный» выше).

Я должен предположить, что это довольно стандартно, но не могу найти пример в книге, и я просто не могу заставить его работать.


Редактировать:

Я также попробовал это:

//VideosTable
public function initialize(array $config)
{
$this->belongsToMany('Categories', [
'through' => 'Categorized',
'conditions' => [
'Categorized.model' => $this->alias(),
]
]);
}

public function getTopVideosByCategory($categorySlug)
{
return $this->find('all')
->matching('Categories', function ($q) use ($categorySlug) {
return $q
->where(['Categories.slug' => $categorySlug]);
})
->contain([
'Tags',
'Categories'
])
->limit(8)
->order([
'Videos.featured' => 'DESC',
'Videos.created' => 'DESC'
])
->first();
}

Но получите эту ошибку:

Ошибка: SQLSTATE [42S22]: столбец не найден: 1054 неизвестный столбец
«Категоризованный.модель» в «по предложению»

1

Решение

Поскольку видео и категории не являются 1-1 o n-1 (hasOne или ownTo), невозможно создать выражение SQL, которое может включать условия для другой таблицы. Для этих случаев CakePHP реализует matching() функция. Работает аналогично contain() но он использует INNER join для получения данных от внешних ассоциаций:

http://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html#filtering-by-associated-data

Вы также можете посмотреть пример использования здесь:

http://book.cakephp.org/3.0/en/tutorials-and-examples/bookmarks/intro.html#creating-the-finder-method

3

Другие решения

Я закончил тем, что заставил это работать так:

class VideosTable extends Table
{
public function initialize(array $config)
{
$this->hasMany('Categorized', [
'foreignKey' => 'foreign_key',
'conditions' => [
'Categorized.model' => $this->alias(),
]
]);
}

public function getTopVideosByCategory($categorySlug)
{
return $this->find()
->matching(
'Categorized.Categories', function ($q) use ($categorySlug) {
return $q
->where(['Categories.slug' => $categorySlug]);
})
->limit(8)
->order([
'Videos.featured' => 'DESC',
'Videos.created' => 'DESC'
])
->all();
}

Я проголосовал за ответ Хосе, так как он помог мне разобраться в этом, но пометит это как ответ, так как я думаю, что он быстрее поможет пользователям, пытающимся разобраться с этой конкретной проблемой.

Хосе, если вы хотите добавить это (с любыми изменениями, которые сочтете нужным) к своему ответу, я заменю отмеченный ответ на ваш.

1

Кажется, что вы хотите:

$this->belongsToMany('Categories', [
'through' => 'Categorized',
'conditions' => ['Categorized.model' => $this->alias()]
]);
0