CCK: сложные поля, сложные связи между документами — возможно ли?

Главные вкладки

Аватар пользователя andyceo andyceo 31 июля 2008 в 9:30

Друзья, при разработке очередного сайта на Drupal у меня вновь возник вопрос. Прошу помощи, ибо сам уже с неделю думаю над задачей — и вижу приемлемое решение только в том, чтобы отказаться от CCK и написать свой модуль.

Итак, ДАНО:
Есть сайт с афишами фильмов. Афиша — это тип контента, созданный при помощи CCK. У него сейчас такие поля:

Название (стандартное поле title)
Описание (стандартное поле body)
Постер (картинка фильма, Imagefield + ImageCache)
Дата показа (дата, делается модулем Date)
Кинотеатр (Ссылка на ноду, Nodereference)
Жанр (обычное текстовое поле с множественным выбором)
Режиссёр (простое текстовое поле)
В ролях (простое текстовое поле)
Рецензия (простое текстовое поле)
Выпущено (простое текстовое поле)
Сценарий (простое текстовое поле)

Итак, в текущем режиме всё работает идеально: Узнаётся в каком кинотеатре будет идти тот или иной фильм, узнаётся дата-время премьеры и последнего показа фильма, ну и затем заполняется афиша. Несложно? Несложно. Вот пример заполненной афишы:

Однако, что получается. В базе данных забито множество кинотеатров. И замечательный мультик «Валл-И» показывается если не во всех, то во множестве кинотеатров. И для того, чтобы оповестить пользователей об этом, нужно создать подобную авфишу ДЛЯ КАЖДОГО КИНОТЕАТРА И ДЛЯ КАЖДОЙ ДАТЫ. Т.е., если у меня в базе данных кроме кинотеатра «Руслан», есть ещё кинотеатр «Космос», то мне нужно создать афишу со следующим содержанием:

Жирным показаны те поля, которые отличаются от аналогичных полей предыдущей афишы.

Разумеется, это неэффективно — у меня получается множество практически одинаковых афиш, и на странице просмотра последних афиш у меня будет длинный список с одной и той же картинкой, одинаковым текстом и т.д. Раумеется, помимо раздражения пользователей, можно ещё и бан поисковых систем получить.

Итак, сформулируем задачу:

Нужно реализовать следующую афишу:

Здесь, строка «Кинотеатр / Дата: Руслан / 10.07.2008 18:21 - 23.07.2008 10:00» расшифровывается так: Кинотеатр / дата премьеры в этом кинотеатре / дата последнего показа этого фильма в этом кинотеатре.

ЗАДАЧА:
То есть, при создании афиши, нужно иметь возможность задать СЦЕПЛЕННЫЕ ПОЛЯ — в данном случае, забить поле Кинотеатр и сразу же для этого поля задать дату. Если у меня есть ешё кинотеатры, в которых пройдёт этот же фильм, то я должен опять — выбрать Кинотеатр и сразу же заполнить поле Даты для этого кинотеатра.

РЕШЕНИЕ №1
В CCK есть хорошая возможность: можно каждому полю приписать «множественность», и забив одно значение, можно забить ещё столько, сколько нужно. (Это делается при настройке поля, во вкладке «Общие настройки», Параметр «Количество значений»: установить в «Неограничено») Однако это работает для ОДНОГО ПОЛЯ. Я же хочу, чтобы подобная возможность работала для группы полей (в данном случае, опять же, речь идёт о Кинотеатре и Дате). Т.е. заполнив одну пару полей, я хочу, чтобы были показана другая пара полей.

Можно, конечно, сделать для каждого из сцепленных полей (Кинотеатр и Дата) установить Количество значений в «Неограниченно», и вводить их по очереди. Ввёл 3 Кинотеатра, потом принялся за даты: ввёл три даты премьер, ввёл три даты последнего показа. Затем, при выводе материалов, нужно будет смотреть какие даты к какому кинотеатру относятся, сопоставляя порядковые номера массивов. Первый кинотеатр — первая дата премьеры — первая дата последнего показа и т.д.

Однако минусы этого подхода очевидны:

  • это неудобно визуально,
  • пользователь легко может ошибиться при сопоставлении какому кинотеатру — какая дата,
  • невозможно задать «жёсткий режим»: например, нельзя задавать три даты премьеры, если задан только один кинотеатр и т.д. - проверку этого известными мне способами с помощью CCK сделать невозможно.

Но есть и другой способ..

РЕШЕНИЕ №2
Разбить данную связь много-ко-многим на две 1-ко-многим. Разбиваем сущность «Афиша» на две сущности: «Фильм» и собственно «Афиша».

Вот такими полями будут обладать эти сущности:

Нода типа "Фильм":

Нода типа "Кинотеатр":

Нода типа "Афиша":

В сущности «Афиша», у нас поля Фильм и Кинотеатр, выделенные жирным курсивом, будут ссылками на ноды (Nodereference — поле).

Таким образом, мне, чтобы ввести афишу, придётся сначала забить фильм, а затем уже создать афишу фильма. И создавать отдельную афишу фильма на каждый день и на каждый кинотеатр.

Однако в этом случае у меня остаётся неразрешённым вопрос: а как мне выводить афишу в таком виде:

С помощью модуля Views я не знаю, как это сделать.

Вот если писать свой модуль, и работать напрямую с базой данных, то любое из вышеописанных решений делается элементарно — я знаю как это делать, и это делается всё очень просто, а вот если делать с помощью CCK — то у меня тут затруднения, не знаю как.

В общем, дорогое друзья, прошу помощи. Может есть какие-то другие решения?

Комментарии

Аватар пользователя KCEOH KCEOH 31 июля 2008 в 9:46

А что мешает юзать словари со свободным заполнением? Создаем ноду (фильм), а дальше указываем в словаре КИНОТЕАТРЫ название этих кинотеатров. Ну и для остального также, я не думаю, что там много новых жанров наизобретали Smile И заполнять проще и быстрее будет.

Далее по дате какие соображения... Дать доступ юзерам редактировать эту ноду, но с ограничением по полю (есть cck-модуль). Типа cck_date_ruslan для представителей Руслана, cck_date_kosmos для Космоса. Текст ноды или в отдельное cck поле выносить, или редактрование темизировать так, чтоб народ не смог текст перебодяжить.

Аватар пользователя kyky kyky 31 июля 2008 в 10:02

автор, по поводу CCK:
используйте связи многие ко многим через node reference и вложенные виды views field

этим viws field можно передавать аргументы, в основном это NID, но можно и другие, например время и так далее...
Можно сделать макет сложной страницы через panels, они поддерживают передачу аргументов
всё что вам нужно - это написать схему данных на бумажке, установить связи и воспользоваться указанными модулями.
Я уже давно практикую вывод сложных материалов с помощью связией главных и дочерних нод. Аргументы передаются через views или panels/

Аватар пользователя andyceo andyceo 31 июля 2008 в 9:59

KCEOH, спасибо за ответ, но Вы написали его, наверное, ещё до того, как я закончил редактировать сообщение и вставлять картинки.

У меня несколько другой вопрос...

За совет разграничить доступ по полям спасибо, однако в вашей схеме получается, что я должен ввести столько полей вроде cck_date_ruslan, сколько у меня кинотеатров, а это не самая лучшая идея Smile

что-то вот в голове вертится решение, да никак не сформулируется что-то... Smile

Аватар пользователя kyky kyky 31 июля 2008 в 10:21

вот решение:

[тип ноды фильм]<-------->[прокат в киноеатре]<-------->[кинотеатр]

вы выводите ноду [прокат в кинотеатре], захватывая материал про фильм и сами кинотеатры

Аватар пользователя andyceo andyceo 31 июля 2008 в 10:37

kyky, спасибо за наводку.

Сразу же поискал на оф. сайте модуль views field, но нашёл только это: Views Tabs, Views Static Field

Нашёл модуль Viewfield, может вы про него мне говорили? Вроде по описанию подходит: When the node is displayed, the view is run and the content is inserted into the body of the node...

Буду копать, спасибо!

Аватар пользователя andyceo andyceo 31 июля 2008 в 10:44

Да, kyky, ещё раз спасибо! Кажется это то что надо. Я просто не знал про модуль Viewfield.

Наверное у меня ещё остались вопросы по разграничению доступа к полям, нодам и апгрейде на 6-ку, только сейчас я не могу их сформулировать...

Аватар пользователя andyceo andyceo 31 июля 2008 в 14:59

kyky, а как сделать так, чтобы при создании документа типа [прокат в киноеатре] , как Вы предложили, у представителей кинотеатра "Космос" (это определённая роль пользователей) отображался только кинотеатр "Космос" в списке кинотеатров, а не все кинотеатры из базы данных?

Аватар пользователя jason32 jason32 31 июля 2008 в 16:35

andyceo
Сделать автором ноды Космоса данного пользователя, а список кинотеатров выводить через Views с фильтром "текущий пользователь"

Аватар пользователя andyceo andyceo 31 июля 2008 в 22:56

jason32, спасибо!

Но я извиняюсь, а можно ли как-то посложнее задать фильтр? например, автор документа + админ + модераторы.

Дело в том, что у меня там довольно сложная система ролей на сайте - есть верховный админ, есть модераторы афиш (ибо один я всё не осиляю). Можно ли в фильтрах Views'а делать выборки в зависимости от ролей пользователя? (Наверное я очень плохо знаю Views... извиняюсь если вопросы нубские...)

Подскажите, пожалуйста! Или ткните меня носом в мануал,я вкурю! Заранее спасибо...

Аватар пользователя batbug batbug 2 августа 2008 в 4:44

на своем сайте я делал уже две версии афиши с помощью view и сск.

в данный момент рабочий вариант такой:

есть ноды типа фильм (набор полей примерно как тут http://www.drupal.ru/files/images/db_entry_film_tn.gif
есть ноды типа афиша (время) и там из полей только: название, node reference на тип фильм, в поле описание руками пишется, в каком кинотеатре какие сеансы, ну и cck_date. и все. вывод этого всего осуществляется через views типа лист, и уже в шаблоне из поля с node_reference nid получается нода с описанием фильма.
У этого способа огромный плюс, в том, что можно задавать афишу на каждый день, ведь известно, что сеансы день ото дня могут меняться.

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

В предудущей версии афиши я пользовался таксономией и имел лишь один тип материалов (описание). На каждый кинотеатр я создавал свой словарь и привязывал его к описанию фильма. Терминами в словаре было время начала сеанса. В принципе, если скомбинировать этот подход с текущим вариантом, то получится совсем хорошо, но! Почему я отказался от варианта с таксономией? Таксономия, да еще с выборкой терминов по куче словарей - это все ужасно медленно, просто ужасно медленно было. Ну по крайней мере в моей конфигурации: у меня на страниче должно было грузиться порядке 20-30 фильмов.

Надеюсь, чем-то помог.

Аватар пользователя andyceo andyceo 14 августа 2008 в 1:03

Спасибо всем ответившим! Извиняюсь, что отвечаю так поздно.

К сожалению, модуль Viewfield не подошёл, т.к. у него нельзя задать динамические аргументы к Views. Скажем, у меня создан Вид, в него в качестве аргумента передаётся ID ноды, вид выдаёт документы. Так вот, когда я создаю тип материала, использующий данный вид, я не могу указать в качестве аргумента ID текущей ноды, например. Только константу какую-то.

Нашёл решение в виде вставки вида вручную из шаблона: Inserting Views. Также изучаю эту тему: How can I make an embedded view take an argument from a URL?