Многие ко многим
Для построение соотношения "многие ко многим" между двумя моделями необходимо в массив "$model_elements" дописать код нового поля и создать связующую таблицу в базе данных. Новое поле в таблицу модели добавлять не нужно. Дополнительные настройки для поля представлены в описании типа данных Многие ко многим "many_to_many".
Например мы хотим связать Предустановленные модели "Pages" и "Blocks" соотношение многие ко многим, для того чтобы иметь возможность включать и отключать блоки на каждой конкретной странице.
class Pages extends Model { protected $name = "Меню страниц"; protected $model_elements = array( ... array("Текстовые блоки", "many_to_many", "blocks", array("related_model" => "Blocks", "linking_table" => "pages_blocks")) ); }
//Структура таблицы "pages_blocks" (внимание на названия полей!) CREATE TABLE "pages_blocks" ( "pages_id" INTEGER, "blocks_id" INTEGER )
Внимание! Связующая таблица для двух моделей должна строиться исходя из их названий. Например есть 2 модели "Albums" и "Images", тогда таблица будет называться "albums_images", а колонки в ней соответственно "albums_id" и "images_id". Поле "id" в связующих таблицах не нужно.
Теперь в административном интерфейсе модели Pages появится поле для выбора блоков, которые относятся к данной модели. В модели Blocks пока нет такого поля. Если мы хотим, чтобы оно было и во второй модели то также добавляем код в файл модели.
class Blocks extends Model { protected $name = "Текстовые блоки"; protected $model_elements = array( ... array("Страницы меню", "many_to_many", "pages", array("related_model" => "Pages", "linking_table" => "pages_blocks")) ); }
Внимание! Когда создается обратная связь "многие ко многим" (например от модели "Blocks" к модели "Pages") название поля ("pages") должно совпадать с названием связанной модели. Смотрите предыдущий пример. Тогда в административной панеле в общей таблице создаются ссылки на вторую модель для запуска фильтра по этому полю.
Когда нужно вывести записи, связанные соотношением "многие ко многим", можно воспользоваться JOIN запросом (в этом случае используются Прямые запросы), либо разбить извлечение записей на 2 запроса как на примере ниже, где выводятся все активные блоки текущей страницы.
//В модели "Blocks" добавляем новый метод public function getRelatedBlocks($page_id) { //Выбираем id всех блоков, относящихся к данной странице $blocks_ids = $this -> selectColumn(array("fields->" => "blocks_id", "pages_id" => $page_id, "table->" => "pages_blocks")); //Если это не предусмотреть в оператор "id->in" пойдет пустая строка и возникнет SQL ошибка if(!count($blocks_ids)) return; $html = ""; //Извлекаем содержимое активных блоков $rows = $this -> select(array("id->in" => implode(",", $blocks_ids), "active" => 1)); foreach($rows as $row) { $html .= "<h3>".$row["name"]."</h3>"; $html .= "<div>".$row["content"]."</div>"; } return $html; }
Предыдущий раздел
Деревья