Разработка Для Drupal 7 С Использованием Новой Концепции Entity.

Концепция Entities, о которой пойдет речь в этой статье, является одной из новых возможностей, представленных в Drupal 7. Чтобы понять новизну предлагаемого подхода, следует совершить небольшой экскурс в историю и вспомнить, как все было в Drupal. 6.



Что это такое, с чем его едят?

Все модули, написанные для Drupal, можно разделить на две категории.

Первый — это модули, которые фактически не объявляют новые типы данных и работают с данными, которые уже определены и где-то хранятся.

Например, модуль Lightbox2 позволяет менять представление изображений на сайте, а модуль devel предоставляет различные полезные разработчику утилиты.

И хотя модуль devel хранит некоторую информацию в базе данных (время выполнения sql-запросов, например), по сути его нельзя назвать полноценной моделью данных.

Вторая категория — это модули, которые позволяют создавать новые типы объектов и определять новые модели данных.

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

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

Первый вариант — определить ваш тип данных как новый тип материала (тип узла).

Второй вариант — создать все с нуля.

Оба подхода имеют свои преимущества и недостатки.

Понятно, что второй вариант более гибкий и не накладывает на вас практически никаких ограничений по реализации.

Первый вариант удобнее и быстрее реализовать за счет готовых инструментов, предоставляемых Node API. Однако не только из-за скорости и простоты разработки большинство серьезных модулей, созданных для Drupal 6 и реализующих какую-то новую модель данных, декларируют ее как тип узла.

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

Такой подход позволяет написать один модуль для расширения функционала всех типов материалов, существующих в системе.

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

Яркими примерами являются модули CCK и Views. Казалось бы, все хорошо, но остается одна проблема.

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

В частности, сложно представить пользователей или комментарии, реализованных как типы контента в Drupal 6. Конечно, здесь можно сколько угодно дискутировать на тему возможности или невозможности реализации пользователей в виде типов материалов.

, но в любом случае этот подход нельзя назвать элегантным и правильным.

Что изменилось с появлением Drupal 7? По сути, был создан новый уровень абстракции.

И зовут его Сущность.

По сути, Entity — это более низкий уровень абстракции, чем node в Drupal 6. Сразу оговорюсь, что в Drupal 7 узлы никуда не исчезли, однако теперь они являются надстройкой над Entity. Самое приятное то, что пользователи, комментарии и многое другое в Drupal 7 также являются сущностями.

Вы можете почувствовать разницу прямо из коробки.

Например, раньше с помощью модуля CCK можно было только добавлять новые поля к типам материалов.

В Drupal 7 вы можете делать то же самое с пользователями, комментариями и даже тегами таксономии.

Это связано с тем, что теги, контент, комментарии и пользователи являются подклассами Entity.

Вскрытие покажет

Прежде чем начать обсуждение внутреннего устройства системы сущностей, следует вспомнить такой замечательный ресурс, как api.drupal.org , где вы всегда сможете ознакомиться со всеми интерфейсами, классами и методами, рассмотренными ниже, на языке Шекспира.

Итак, пришло время посмотреть, как все это работает. Несмотря на то, что (как мы увидим позже) в Drupal 7 значительно расширилось использование объектно-ориентированного программирования, чтобы сообщить системе, что наш модуль реализует новую сущность, нам потребуется реализовать перехватчик.

Нас интересует крючок ook_entity_info() .

Из него мы должны вернуть ассоциативный массив, ключами которого будут имена сущностей, которые мы будем реализовывать.

В свою очередь, каждая сущность будет иметь соответствующий массив своих параметров.

Ниже приведен список параметров, которые мы можем указать:

  • label: так называемое «читабельное» имя нашего типа сущности.

    Должен быть обернут в t(), если вы хотите, чтобы метка была переводимой.

  • Класс контроллера: имя класса контроллера, который будет отвечать за загрузку данных.

    Класс должен реализовывать интерфейс DrupalEntityControllerInterface. Если вы не укажете этот параметр, в качестве контроллера будет использоваться контроллер по умолчанию — DrupalDefaultEntityController (Контроллеры сущностей будут рассмотрены далее в статье).

  • базовая таблица: базовая таблица в базе данных для нашей сущности.

    Формально параметр является необязательным, поскольку используется классом DrupalDefaultEntityController и его наследниками.

    Те.

    Вы можете реализовать интерфейс DrupalEntityControllerInterface по-своему и получать данные не из таблицы базы данных, а даже с марсианского спутника, но если вы решите использовать в качестве контроллера DrupalDefaultEntityController или производную от него, укажите этот параметр.

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

  • Таблица ревизий: Аналогично предыдущей, но в данном случае это таблица ревизий.

    Здесь есть справедливая аналогия с узлами.

    Если вашему объекту не требуются разные версии, этот параметр можно опустить.

  • статический кеш: еще один параметр, используемый DrupalDefaultEntityController. Включает статическое кэширование сущностей во время запроса страницы.

    Те.

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

    Таким образом, если запрос не планирует менять сущность и затем загружать ее снова, имеет смысл установить для нее значение TRUE (или просто опустить параметр, поскольку по умолчанию он уже TRUE).

  • кэш полей: Здесь речь идет о постоянном кэше по отношению к полям (Field API), который, как будет показано позже, можно прикреплять к сущностям.

    В официальной документации говорится, что установка для этого параметра значения FALSE имеет смысл только в том случае, если весь объект постоянно кэшируется.

    Другими словами, если вы не знаете точно, зачем вам это нужно, лучше этот параметр опустить и запомнить, что по умолчанию он установлен в TRUE.

  • привязка загрузки: еще один параметр, используемый в DrupalDefaultEntityController. Вызывается функцией DrupalDefaultEntityController:attachLoad и позволяет другим модулям прикреплять свою информацию к сущности.

    Функция Attach_load в любом случае вызоветook_entity_load для всех сущностей, но указанный крючок загрузки позволит вам вызвать отдельный крючок для вашей сущности (например,ook_node_load в модуле узла).

  • Обратный вызов uri: принимает сам объект в качестве аргумента.

    Возвращает компоненты uri объекта (например, путь и параметры), из которых позже можно получить адрес объекта с помощью функции uri().

    Существуют разные подходы к определению этой функции.

    В модуле Entity API, в частности, есть функцияentity_class_uri, которая просто вызывает функцию $entity-> uri() переданной ей сущности, тем самым позволяя сущности самой определить свой адрес.

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

    Принимает саму сущность и тип сущности в качестве аргументов.

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

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

  • fieldable: Как говорится, «и в этом вся магия».

    Установив для него значение TRUE и при условии, что ваш контроллер реализует эту функциональность (или унаследован от DrupalDefaultEntityController), вы делаете свою сущность расширяемой с помощью Drupal Field API (аналог CCK для Drupal 6 в Drupal 7, интегрированный в ядро).

    Те.

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

  • перевод: Не вдаваясь в подробности, это поле позволяет вам сделать вашу сущность и прикрепленные к ней поля переводимыми.

    Если не пусто, значение представляет собой ассоциативный массив, где ключами являются имена модулей, обеспечивающих возможности перевода, а значениями — информационные структуры любого вида, необходимые для перевода.

  • ключи сущности: параметр, используемый Field API. Ассоциативный массив, который может включать в себя следующие элементы:
  • - id: поле сущности, содержащее уникальный первичный идентификатор сущности.

    Обязательный параметр, если для поля установлено значение TRUE. Значение должно быть положительным целым числом.

  • — ревизия: имя параметра, содержащего идентификатор ревизии.

    Field API предполагает, что все сущности внутри типа имеют уникальный идентификатор версии.

    Если ваша организация не реализует модель версии (ревизии), то параметр можно опустить.

  • — Bundle: параметр, указывающий, к какому пакету (подтипу) принадлежит объект. Каждый пакет имеет свой набор полей.

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

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

    Тогда имя типа сущности будет автоматически использоваться в качестве параметра.

  • — метка: параметр, указывающий имя объекта.

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

  • Bundles: Фактически определяет набор пакетов (подтипов) нашего типа сущности.

    Ассоциативный массив, ключами которого являются машинные имена пакетов (в той форме, в которой они хранятся в поле «bundle», определенном в параметре «entitykeys»).

    Имена связок, в свою очередь, связаны ассоциативными массивами со следующими ключами:

  • — метка: «читабельное» имя пакета.

    Как обычно, мы обертываем его в t(), если хотим, чтобы имя было переведено.

  • — Обратный вызов uri: То же, что и «обратный вызов uri» для типа сущности, только для пакета.

    Если указаны оба, будет использоваться обратный вызов для пакета.

  • - admin: массив с информацией, которая позволит Field API встраивать свои страницы в страницы администрирования объекта.

  • — путь: Путь к странице администрирования пакета.

    Если путь включает заполнитель, вам также необходимо будет указать значения для «аргумента пакета» и «реального пути» (обсуждается ниже).

  • — — аргумент пакета: положение заглушки в пути.

    Принцип тот же, что и при работе с путями меню.

  • — — реальный путь: Путь к странице администрирования пакета без заглушки.

    Будет использоваться для генерации ссылок.

  • — — обратный вызов доступа: То же, что и вook_menu().

    Если оставить пустым, будет использоваться user_access().

  • — — аргументы доступа: такие же, как вook_menu().

  • Режимы просмотра: Различные способы (типы) отображения объекта.

    Хороший пример — полный тизер в node. Ассоциативный массив, который использует имена машинных представлений в качестве ключей.

    По умолчанию каждая сущность имеет представление по умолчанию.

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

  • — этикетка: «читабельное» название вида.

    Как обычно, мы обертываем его в t(), если хотим, чтобы имя было переведено.

  • — пользовательские настройки: Строго говоря, этот параметр относится в первую очередь к полям.

    Если установлено значение FALSE (значение по умолчанию), то первоначально представление унаследует настройки отображения полей из представления по умолчанию.

    Затем настройки можно изменить через интерфейс поля.

Фактически это все параметры, которые можно указать для типа сущности.

Следует отметить, что дополнения для DrupalDefaultEntityController, такие как, например, EntityAPIController, могут требовать/использовать дополнительные параметры.

Например, EntityAPIController использует параметр «класс объекта».

Эта возможность достигается благодаря функцииentent_get_info($entity_type=NULL), которая позволяет получить данные о нужном типе сущности.



Контроллер сущности
Теперь давайте подробнее рассмотрим контроллер сущности, который определен в параметре «класс контроллера».

По сути, контроллер — это способ управления данными вашей организации.

Что мне нравится в ООП, так это то, что оно не только позволяет сделать более эффективным сам код, но и облегчает понимание процессов, происходящих внутри него.

Чтобы понять, как работает контроллер, начнем с самого низу.

По определению параметр «класс контроллера» должен указывать класс, реализующий интерфейс.

DrupalEntityControllerИнтерфейс .

И несмотря на кажущуюся сложность концепции сущностей, этот интерфейс на удивление минималистичный.

Предполагается, что наш класс реализации имеет только три метода: DrupalEntityControllerInterface::load — Загружает один или несколько объектов.

В качестве первого аргумента он принимает массив идентификаторов сущностей, которые необходимо загрузить.

В качестве второго аргумента он принимает массив условий в форме «поле» => «значение».

DrupalEntityControllerInterface::resetCache — очищает (сбрасывает) статический кеш для всех сущностей (если аргумент не указан) или для выбранного набора сущностей (если в качестве аргумента передается соответствующий массив идентификаторов) DrupalEntityControllerInterface::__construct — Конструктор.

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

Таким образом, зная тип сущности, для которой создается контроллер, вы можете получить параметры этого типа с помощьюentity_get_info($entity_type) и настроить созданный экземпляр контроллера.

Это собственно все методы, которые необходимо реализовать в вашем классе, чтобы он имел полное право называться контроллером сущности.

Однако в большинстве случаев имеет смысл не реализовывать интерфейс с нуля, а наследовать свой класс контроллера от класса DrupalDefaultEntityController который мы сейчас рассмотрим.

Что нам дает DrupalDefaultEntityController?

  1. Возможность загрузки любых сущностей независимо от типа из таблиц базы данных, указанных в параметрах «базовая таблица» и «таблица ревизий» типа сущности.

  2. Прикрепляет поля к нашей сущности с помощью Field API, если для типа сущности установлено значение TRUE.
  3. Возможность эффективной загрузки сущностей.

    Класс реализует поддержку статического кэширования.

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

Таким образом, DrupalDefaultEntityController не направлен на реализацию функциональности как таковой для конечного пользователя, он лишь предоставляет разработчику некую точку отсчета.

Более того, в тех случаях, когда ваша сущность должна каким-то образом реализовать концепцию CRUD (Create Read Update Delete), имеет смысл наследовать свой контроллер от класса еще более высокого уровня — EntityAPIController, представленного в модуле Entity API. Однако рассмотрение принципов работы с Entity API выходит за рамки данной статьи и будет рассмотрено в другой раз.

Теги: #drupal #drupal 7 #drupalentity #entity #drupal api #drupal

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.