Классы контроллеров для создаваемых сущностей

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

Аватар пользователя roman-yrv roman-yrv 18 апреля 2013 в 19:58

Добрый день.

Сейчас пытаюсь разобраться с созданием своих Entity (сущностей)

И не могу понять, для чего при описании сущности используются контроллеры (классы, наследуемые от DrupalDefaultEntityController) ?

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

Или здесь контроллер служит для того, чтобы доопределить или переопределить какие-то действия, выполняемые с сущностью ?
Но почему в этом случае не воспользоваться друпаловским подходом - написать соответствующий хук, который так же всё это сделает ?

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

Комментарии

Аватар пользователя sg85 sg85 18 апреля 2013 в 20:48

"roman-yrv" wrote:
Ведь в понятиях MVC контроллер - это обработчик определенных запросов к сайту, а это в Drupal реализуется с помощью hook_menu - описываешь путь в меню, какой нужно, и спокойно его обрабатываешь.

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

"roman-yrv" wrote:
Или здесь контроллер служит для того, чтобы доопределить или переопределить какие-то действия, выполняемые с сущностью ?

отчасти, как минимум это загрузка сущности и работа с её внутренним кешем.

"roman-yrv" wrote:
Но почему в этом случае не воспользоваться друпаловским подходом - написать соответствующий хук, который так же всё это сделает ?

Видимо разработчики решили, что так будет лучше, и решили они так наверняка не на пустом месте.

"roman-yrv" wrote:
Просто смущает и запутывает некая двойственность - с одной стороны, система хуков, в которых можно описать структуры и выполнить свои действия, а с другой стороны, классы и наследование.

В некоторых случаях выгоден ООП с наследованиями, в некоторых система хуков. Так же не забываем, что ООП в PHP ест довольно много ресурсов, потому бездумно тыкать его направо и налево не стоит.

Аватар пользователя roman-yrv roman-yrv 18 апреля 2013 в 21:14

А такой еще вопрос.

Кроме класса контроллера есть класс сущности Entity.

Для чего его используют при создании сущности ?
И в каким случаях от Entity наследуется свой класс для данной сущности ?

Аватар пользователя sg85 sg85 19 апреля 2013 в 0:04

"roman-yrv" wrote:
Кроме класса контроллера есть класс сущности Entity.

впервые про него слышу.

Допускаю, что он относится к модулю Entity Api, но мне этот модуль пока не пригодился(в плане кодить под него), так что про него рассказать ничего не могу.

Аватар пользователя roman-yrv roman-yrv 19 апреля 2013 в 7:53

Ну вот, например:
http://xandeadx.ru/blog/drupal/352

function album_entity_info() {
  return array(
    'album' => array(                               // Системное имя сущности
      'label' => t('Album'),                        // Человеко-понятное имя сущности

      'entity class' => 'Entity',                   // Класс сущности

      'controller class' => 'EntityAPIController',  // Контроллер сущности
      'base table' => 'albums',                     // Таблица, в которой хранится информация об альбомах
      'entity keys' => array(
        'id' => 'aid',                              // Название поля, в котором распологаются идентификаторы альбомов
        'label' => 'title'                          // Название поля, в котором распологаются названия альбомов
      ),
      'admin ui' => array(
        'path' => 'admin/structure/albums'          // Путь, по которому будет доступна админка
      ),
      'access callback' => 'album_access',          // Имя функции, отвечающей за проверку прав доступа
      'module' => 'album',
    ),
  );
}

Да, он относится к Entity API.

Аватар пользователя sg85 sg85 19 апреля 2013 в 18:05

Вот это уже больше похоже на модель(+кое что, чего не хватает в контроллере), используется для реализации функционала модуля Entity Api, необязательный параметр, лично мне не совсем понятно почему все сделано именно так, видимо надо "поиграться" с ним, ибо действительно подход несколько расходится с друпаловским, подобная реализация идет у views, но там и при беглом осмотре понятно, что, к чему и почему. По умолчанию(в ядре, без модуля Entity Api) контроллер там не полноценный да и модель разнесена по функциям использующим сущности так, что кажется, будто она вообще отсутствует, видимо тут попытка привести все это дело к более или менее вменяемому MVC. НО это уже ИМХО.

Аватар пользователя sg85 sg85 19 апреля 2013 в 18:19

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

Аватар пользователя roman-yrv roman-yrv 19 апреля 2013 в 21:26

Так а разве нельзя переопределить вывод, сохранение и т.д. переопределить с помощью своего наследуемого контроллера ?

Просто вот, например, код функции Entity.save()
http://drupalcontrib.org/api/drupal/contributions%21entity%21includes%21...

public function save() {
  return entity_get_controller($this->entityType)->save($this);
}

Берется контроллер и вызывается save контроллера с данной сущностью.

Аватар пользователя sg85 sg85 20 апреля 2013 в 9:55

Вроде разобрался, весь код должен быть действительно в контроллере(все методы загрузки, сохранения и прочей ерунды), в качестве контроллера для EntityApi обязательно должен наследоваться класс EntityAPIController, т.е. контроллер должен обязательно иметь интерфейс EntityAPIControllerInterface, класс сущности т.е. класс Entity это всего лишь очень неплохая замена для stdClass, т.е. вместо привычного нам node_save($node); можно использовать более удобный и ООПный $entity->save();(со стандартными сущностями не работает, ибо у них класс сущности не задан) необходимость наследовать класс Entity есть только в том случае, если надо прикрутить пару методов к самому классу сущности, например $entity->find_my_beer();

Еще несколько наблюдений:
1. Контроллер сущности необходим для любой сущности, как минимум DrupalDefaultEntityController, чисто для загрузки сущности через entity_load()(ибо по другому сущность то и не загрузить), но это уже ядро.
2. Практически весь функционал модуля Entity Api можно использовать с помощью колбеков, т.е. чисто функционального программирования.
3. Использование класса сущности необязательно, однако, в этом случае придется работать с stdClass.
4. Использование класса сущности возможно только, если контроллер наследуется от EntityAPIController(или, как минимум, им и является).
5. Использовать контроллер EntityAPIController отдельно от класса сущности возможно, однако, ничего кроме более удобного способа определения поведения сущности чем через колбеки это не даст. Лично мне не понятно зачем, но такой ход предусмотрен.
6. Не понял логики приоритетов выполнения - в большинстве случаев, приоритет отдается колбекам, в некоторых случаях напрямую контроллеру, а иногда методам класса сущности, отсюда следует, что пытаться цеплять сразу несколько обработчиков одного и того же процесса, например, с целью перекрытия или других извращений, не стоит, ибо если разработчики не придали этому значения, вполне вероятно, что в будущем он может измениться.

Из всего это следует: наследуем EntityAPIController, используем класс Entity, либо его наследование в случае необходимости, и не паримся.

Аватар пользователя organizm organizm 24 августа 2013 в 1:14

"sg85" wrote:

Если не сложно приведите пример кода. Ато никак не получается програмно создать и сохранить сущность Sad
Делаю вот так:

<?php
$entity_type
='shopping';
$values=array ( 'uid'=>1'date'=>1305116486'count'=>1);
$entity=new Entity($values,$entity_type); 
$entity->save();
?>

Но данные в таблицу так и не попадают.

Аватар пользователя sg85 sg85 24 августа 2013 в 2:17

Ваш код вроде должен работать.
На вскидку:
1 проблема в описании сущности в hook_entity_info();(наиболее вероятно)
2 проблема в контроллере(если используете собственный класс контроллера)

Аватар пользователя organizm organizm 25 августа 2013 в 1:22

Вот что уменя в hook_entity_info(). Клас контролера брал стандартый.

<?php
  
return array(
   
'shopping' => array(                             
      
'label' => t('Shopping'),                       
      
'entity class' => 'Entity',                   
      
'controller class' => 'EntityAPIController'
      
'base table' => 'shopping',                 
      
'entity keys' => array(
        
'id' => 'id'                                                        
      
),
      
'admin ui' => array(
        
'path' => 'admin/structure/shopping'   
      
),
      
'access callback' => 'tf_access',         
      
'module' => 'tf',
    ),   
  );
?>
Аватар пользователя sg85 sg85 25 августа 2013 в 5:19

И объявление сущности должно работать, значит либо ошибка в схеме таблицы, либо таблица в БД не соответствует ей(такое может быть, если например, произошла какая-нибудь ошибка при установке модуля, в данном случае удобно использовать модуль schema.
Пример рабочей схемы для данного случая:

  $schema['shopping'] = array(
    'fields' => array(
      'id' => array(
        'type' => 'serial',
        ...
      ),
      'uid' => array(
        'type' => 'int',
        ...
      ),
      'date' => array(
        'type' => 'int',
        ...
      ),
      'count' => array(
        'type' => 'int',
        ...
      ),
    ),
    'primary key' => array('id'),
    ...
  );
 
 

Ежели и тут все окажется правильно, остается только копать в сторону настроек самого сервера, как минимум проверить логи апача(или что там у Вас) и субд на наличие всяких там нотисов и ворнингов. Ну и конечно убедиться, что Вы не совершали совсем странных ошибок, вроде того, что забыли включить модуль Entity Api, либо хакнули его или ядро, ну и все в таком духе.