Нодус:Связи между материалами
А теперь давайте представим себе, что все коты в нашем каталоге - дрессированные. А если они дрессированные, то должен быть и дрессировщик, которого следует указывать при редактировании параметров кота и выводить на странице описания. Мы, конечно, можем создать словарь, в который занести Куклачева, Запашного и прочих. Однако может так оказаться, что дрессировщик по логике проекта - это нечто большее, чем термин словаря. Это полноценный материал с кучей информации. Т.е. нам нужно создать новый тип материала - trainer (дрессировщик), занести некий набор дрессировщиков, а потом при редактировании кота выбирать дрессировщика из списка.
Для этого в Нодусе предусмотрен механизм связей между материалами.
Единичная связь
Итак, у нас есть тип trainer, дрессировщики занесены. В типе cat создаем поле trainer:
'trainer' => array( 'sqltype' => 'int index', 'type' => 'nodus_items_select', 'selector' => 'trainer', 'caption' => 'Дрессировщик', 'tab' => 'default', ),
- Тип поля nodus_items_select обеспечивает единичную связь. Т.е. конкретному коту может быть сопоставлен только один дрессировщик.
- Параметр selector указывает селектор, выдающий список дрессировщиков для выбора. В данном случае используется селектор по умолчанию, но никто не мешает создать какой-нибудь сложный селектор.
Как отобразить дрессировщика на странице кота
// Получаем контейнер значения $trainer = $item->field('trainer'); // Выводим материал типа trainer в режиме отображения teaser (по умолчанию) print $trainer; // Выводим материал в произвольном режиме отображения print $trainer->render($mode); // Для более низкого уровня - получаем ID дрессировщика $trainer_id = $trainer->id(); // Получаем имя дрессироващика $trainer_name = $trainer->title(); // Получаем ссылку на полную страницу дрессировщика $trainer_url = $trainer->url(); // Получаем весь материал в виде объекта $trainer_item = $trainer->item();
Как вывести список котов на странице дрессировщика
Например, так:
// Получаем селектор, выдающий котов данного дрессировщика $cats_selector = Component_Nodus::selector('cat')->column_eq('trainer',$item->id); // Выводим полный список котов, используя хелпер print $this->nodus->selector_rows($cats_selector); // Выводим список, указывая особый режим отображения print $this->nodus->selector_rows($cats_selector,array('mode' => 'for_trainer')); // Если котов много, то можно вывести первые несколько // (не забываем потом ссылку на весь список) print $this->nodus->selector_rows($cats_selector,array( 'mode' => 'for_trainer', 'limit' => 3 )); // Получаем список котов в виде массива // и делаем с ним что угодно $cats_rows = $cats_selector->rows();
Множественная связь
А теперь представим себе. что у одного кота может быть несколько дрессировщиков (жалко животину, но иногда надо). Поэтому нужна множественная связь. Создаем аналогичное поле без параметра sqltype, но с типом nodus_items_multilink:
'trainers' => array( 'type' => 'nodus_items_multilink', 'selector' => 'trainer', 'caption' => 'Дрессировщик', 'tab' => 'default', ),
И спокойно себе отмечаем дрессировщиков галочками. Если список небольшой, то проблем с его использованием не возникнет. А если список досточно длинный? Тогда воспользуемся модифицированным вариантом данного типа - nodus_items_multilink_advanced. Поступаем аналогично, только в type указываем тип поля nodus_items_multilink_advanced.
'trainers' => array( 'type' => 'nodus_items_multilink_advanced', 'selector' => 'trainer', 'caption' => 'Дрессировщик', 'tab' => 'default', ),
Теперь, в поле «Дрессировщик», будет указана ссылка «Добавить связь». А при добавлении новой связи, откроется модальное окно со списком всех дрессировщиков и формой поиска.
Можно пойти и в обратную сторону: сделать поле cats у материала "Дрессировщик", в котором помечать галками котов. Но тут нужно смотреть по нуждам конкретного проекта и сделать так, как будет удобнее для администрирования.
Как вывести список дрессировщиков на странице кота
Двумя способами. Во-первых, используя возможности самого поля nodus_items_multilink:
// Выводим всех дрессировщиков в режиме отображения по умолчанию (teaser) print $item->field('trainers'); // Выводим всех дрессировщиков в указанном режиме отображения print $item->field('trainers')->render($mode); // Выводим первых трех дрессировщиков в указанном режиме отображения print $item->field('trainers')->limit(3)->render($mode);
Однако этим все возможности поля и ограничиваются. Изменить, например, порядок сортировки уже не получится. Более гибкий способ - получить селектор и работать уже с ним:
// Получаем селектор по-умолчанию для типа trainer // и применяем модификатор - все привязанные к данному материалу // по полю trainers. $selector = Component_Nodus::selector('trainer')->tied_to($item,'trainers'); // Выводим полученных дрессировщиков хелпером print $this->nodus->selector_rows($selector); // Или получаем массив и делаем с ним что угодно $trainers = $selector->rows();
Как вывести список котов на странице дрессировщика
Здесь только один способ - с селектором, т.к. у типа trainer нет поля, отвечающего за котов. Все аналогично предыдущему примеру, только вместо tied_to используем back_tied_to - нам нужна именно обратная свзяь:
$selector = Component_Nodus::selector('cat')->back_tied_to($item,'trainers');
Не перепутайте: вторым аргументом в функции back_tied_to в данном случае будет именно 'trainers', т.к. это - название поля, по которому идет связь. Впрочем, в простейшем случае второй параметр здесь (и в tied_to) можно опустить - тогда будут выбраны все привязанные материалы данного типа, не взирая на имя поля. Когда такое поле одно, разницы нет. А вот если будет два поля (например - "Основные дрессировщики" и "Дублирующие дрессировщики"), то имя поля указывать - обязательно.